昨天有提到,Beautiful Soup 也可以用 lxml
來作為剖析器,但在某些特殊情況還是得回頭以 lxml
來使用 XPath
定位資料。
安裝 lxml
的方式可以參考昨天的文章,今天也沿用昨天的 HTML 原始內容。
html_doc = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title"><b>The Dormouse's story</b></p>
<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>
<p class="story">...</p>
</body></html>
"""
語法 | 說明 |
---|---|
node-name | 選擇名稱等於 node-name 的節點 |
/ | 選擇直屬於當前節點的所有節點(子節點) |
// | 選擇當前節點下所有節點(子孫節點) |
. | 選擇當前節點 |
.. | 選擇上一層節點(父節點) |
@ | 選擇屬性 |
以我們使用的 HTML 原始內容來說:
查詢路徑 | 結果 |
---|---|
/html | 取得 html 標籤(以 / 開頭代表從根節點開始找) |
/html/body/a | 取得 body 下所有 a 標籤(無結果,因為 a 在 p 底下) |
//a | 取得所有 a 標籤 |
/html/body//a | 取得 body 下所有 a 標籤 |
//a/@href | 取得所有 a 標籤的 href 屬性 |
用 lxml 的 etree.HTML()
方法載入 HTML 原始資料後,可以用 .xpath()
方法來執行 XPath 查詢:
from lxml import etree
# 載入 HTML 原始資料
html = etree.HTML(html_doc)
print(html.xpath('/html'))
print(html.xpath('/html/body/a'))
print(html.xpath('//a'))
print(html.xpath('/html/body//a'))
print(html.xpath('//a/@href'))
用 [
和 ]
包起來,用來對查詢加上一些額外的限制
判斷式 | 結果 |
---|---|
/html/body//a[1] | 取得 body 下第一個 a 標籤 |
/html/body//a[last() - 1] | 取得 body 下最後一個 a 標籤 |
/html/body//a[position() < 3] | 取得 body 下前兩個 a 標籤 |
//p[@class] | 取得有定義 class 屬性的 p 標籤 |
//p[@class='title'] | 取得 class 屬性值為 title 的 p 標籤 |
print(html.xpath('/html/body//a[1]'))
print(html.xpath('/html/body//a[last() - 1]'))
print(html.xpath('/html/body//a[position() < 3]'))
print(html.xpath('//p[@class]'))
print(html.xpath('//p[@class="title"]'))
XPath 也支援萬用字元(wildcards)來選取任意節點
萬用字元 | 說明 |
---|---|
* | 任意標籤 |
@* | 任意屬性 |
以我們使用的 HTML 原始內容來說:
查詢路徑 | 結果 |
---|---|
/html/body/* | 取得 body 標籤的全部子節點 |
/html/body//* | 取得 body 下全部標籤 |
//p[@*] | 取得至少有定義一個屬性的 p 標籤 |
print(html.xpath('/html/body/*'))
print(html.xpath('/html/body//*'))
print(html.xpath('//p[@*]'))
如果想要一次查詢多組路徑,可以用 |
來達成。
通常在所需資料分散多處,但不想查詢多次時會用到。(因為分次查詢會打亂資料順序)
查詢路徑 | 結果 |
---|---|
//p | //a | 一次取得全部 p 標籤和 a 標籤 |
print(html.xpath('//p | //a'))
用 Python 來剖析原始資料的方式就介紹到這邊!明天再了解怎麼在網路上取得原始資料後,後天就可以開始蒐集資料囉!